<?php
namespace nimo\domains\car_balance\service;

use \stdClass;
use Carbon\Carbon;
use nimo\domains\car_balance\Model\PurchaseCar;

class SummaryCalcService {
  public static function summary($cars) {
    $services = array ();
    $customers = array ();
    $all = array ();
    $fields = array (
        // 仕入
        'purchase_price',
        'recycle_amount',
        'car_tax_amount',
        'auction_commission',
        'transfer_fee',
        'others',
        'tic_send_fee',
        'vanning',
        'drayage',
        'customs',
        'bl_fee',
        // 請求
        'bill_price',
        'bill_transport_fee',
        'bill_commission',
        'bill_total',
        'bill_vanning',
        'bill_recycle',
        'bill_rakusatu',
        'bill_others',
        // 消費税
        array (
            'name' => 'consumption_tax',
            'calc' => function ($car) {
              return intval ( $car->purchase_price * $car->vat_percent / 100 );
            }
        ),
        array (
            'name' => 'bill_consumption_tax',
            'calc' => function ($car) {
              return intval ( $car->bill_price * $car->bill_vat / 100 );
            }
        )
    );

    if ($cars->count ()) {
      foreach ( $cars as $car ) {
        SummaryCalcService::totals ( $services, $car, 'service_company_id', $fields );
        SummaryCalcService::totals ( $customers, $car, 'customer_id', $fields );
        SummaryCalcService::totals ( $all, $car, 'ALL', $fields );
      }
      ;
      $services ['ALL'] = $all ['ALL'];
      $customers ['ALL'] = $all ['ALL'];
    }
    SummaryCalcService::carTotals ( $services );
    SummaryCalcService::carTotals ( $customers );
    return compact ( 'customers', 'services' );
  }
  protected static function carTotals(&$totals) {
    foreach ( $totals as &$total ) {
      $total ['pay_amount1'] = 0;
      $total ['pay_amount2'] = 0;
      $total ['bill_total'] = 0;
      // 支払１
      foreach ( array (
          'purchase_price',
          'consumption_tax',
          'recycle_amount',
          'car_tax_amount',
          'auction_commission',
          'vanning',
          'drayage',
          'customs',
          'bl_fee'
      ) as $field ) {
        $total ['pay_amount1'] += $total [$field];
      }
      // 支払２
      foreach ( array (
          'pay_amount1',
          'transfer_fee',
          'others',
          'tic_send_fee'
      ) as $field ) {
        $total ['pay_amount2'] += $total [$field];
      }
      // 請求
      foreach ( array (
          'bill_price',
          'bill_consumption_tax',
          'bill_transport_fee',
          'bill_commission',
          'bill_vanning',
          'bill_recycle',
          'bill_rakusatu',
          'bill_others'
      ) as $field ) {
        $total ['bill_total'] += $total [$field];
      }
    }
  }
  public static function summaryParts($parts) {
    $services = array ();
    $customers = array ();
    $all = array ();

    $fields = array (
        'price',
        'delivery_fee',
        'commission',
        'payment_commission'
    );

    if ($parts->count ()) {
      foreach ( $parts as $part ) {
        SummaryCalcService::totals ( $services, $part, 'payment_type', $fields );
        SummaryCalcService::totals ( $customers, $part, 'customer_id', $fields );
        SummaryCalcService::totals ( $all, $part, 'ALL', $fields );
      }
      $services ['ALL'] = $all ['ALL'];
      $customers ['ALL'] = $all ['ALL'];
    }
    return compact ( 'customers', 'services' );
  }
  public static function summaryDocuments($cars) {
    $services = array ();
    $all = array ();
    if ($cars->count ()) {
      foreach ( $cars as $car ) {
        SummaryCalcService::calculateDocuments ( $services, $car, 'service_company_id' );
        SummaryCalcService::calculateDocuments ( $all, $car, 'ALL' );
      }
      ;
      $services ['ALL'] = $all ['ALL'];
    }
    return compact ( 'services' );
  }
  public static function calculateDocuments(&$total, $car, $group) {
    $group = ($group == 'ALL') ? 'ALL' : $car->$group;
    if (! array_key_exists ( $group, $total )) {
      $total [$group] = array ();
      $total [$group] ['id'] = $group;
      $total [$group] ['count'] = 0;

      $total [$group] ['recycle_amount'] = 0;
      $total [$group] ['recycle_amount_count'] = 0;

      $total [$group] ['returned_recycle'] = 0;
      $total [$group] ['returned_recycle_count'] = 0;

      $total [$group] ['recycle_application_date_count'] = 0;

      $total [$group] ['car_tax_amount'] = 0;
      $total [$group] ['car_tax_amount_count'] = 0;

      $total [$group] ['car_tax_cancel_amount'] = 0;
      $total [$group] ['car_tax_cancel_amount_count'] = 0;

      $total [$group] ['car_tax_cancel_count'] = 0;

      $total [$group] ['car_liability_insurance_cancel_amount_count'] = 0;
      $total [$group] ['car_liability_insurance_cancel_amount'] = 0;

      $total [$group] ['car_liability_insurance_cancel_count'] = 0;
    }
    $a = &$total [$group];
    if ($car->recycle_amount > 0) {
      $a ['recycle_amount'] += $car->recycle_amount;
      $a ['recycle_amount_count'] += 1;
    }
    if ($car->returned_recycle > 0) {
      $a ['returned_recycle'] += $car->returned_recycle;
      $a ['returned_recycle_count'] += 1;
    }
    if (! is_null ( $car->recycle_application_date ) && $car->recycle_application_date > '0') {
      $a ['recycle_application_date_count'] += 1;
    }

    // -- TODO INSURANCE,CONATINER --

    if ($car->car_tax_amount > 0) {
      $a ['car_tax_amount'] += $car->car_tax_amount;
      $a ['car_tax_amount_count'] += 1;
    }
    if ($car->car_tax_cancel_amount > 0) {
      $a ['car_tax_cancel_amount'] += $car->car_tax_cancel_amount;
      $a ['car_tax_cancel_amount_count'] += 1;
    }
    if (! is_null ( $car->car_tax_cancel ) && $car->car_tax_cancel > '0') {
      $a ['car_tax_cancel_count'] += 1;
    }

    if ($car->car_liability_insurance_cancel_amount > 0) {
      $a ['car_liability_insurance_cancel_amount'] += $car->car_liability_insurance_cancel_amount;
      $a ['car_liability_insurance_cancel_amount_count'] += 1;
    }
    if (! is_null ( $car->car_liability_insurance_cancel ) && $car->car_liability_insurance_cancel > '0') {
      $a ['car_liability_insurance_cancel_count'] += 1;
    }

    $a ['count'] += 1;
  }
  public static function totals(&$total, $data, $group, $fields) {
    $group = ($group == 'ALL') ? 'ALL' : $data->$group;
    if (! array_key_exists ( $group, $total )) {
      $total [$group] = array ();
      $total [$group] ['id'] = $group;
      $total [$group] ['count'] = 0;
      foreach ( $fields as $field ) {
        if (is_string ( $field )) {
          $total [$group] [$field] = 0;
        } else if (is_array ( $field )) {
          $total [$group] [$field ['name']] = 0;
        }
      }
    }
    ;
    $a = &$total [$group];
    foreach ( $fields as $field ) {
      if (is_string ( $field )) {
        $a [$field] += $data->$field;
        // $a[$field] += is_null($data->$field) ? 0 : $data->$field;
      } else if (is_array ( $field )) {
        $a [$field ['name']] += $field ['calc'] ( $data );
      } else if (is_callable ( $field )) {
        $field ( $data, $a );
      }
    }
    $a ['count'] += 1;
  }

  protected static $FIELDS = array (
       //仕入　合計           購入額           消費税               自動車税         R料             落札料                Vanning       陸送           その他    送料
      'payment_total_amount','purchase_price','purchase_price_tax','car_tax_amount','recycle_amount','auction_commission','vanning',     'transfer_fee','others','tic_send_fee','drayage', 'customs', 'bl_fee',
       //請求　合計           購入額           消費税               手数料           R料             落札料                Vanning、     陸送                 その他
      'bill_total_amount',   'bill_price',    'bill_price_tax',   'bill_commission','bill_recycle','bill_rakusatu',       'bill_vanning','bill_transport_fee','bill_others',
      //R返戻額
      );
  public static function create_summary($recid) {
    $obj = new stdClass ();
    $obj->count = 0;
    foreach (static::$FIELDS  as $f ) {
      $obj->$f = 0;
    }
    $obj->recid = $recid;
    return $obj;
  }

  public static function summary_between($cars, $date) {
    $s =new stdClass ();
    $recid = 1;
    $all = static::create_summary($recid++);
    $s->car = array();
    $s->service = array();
    $s->customer = array();
    $s->auction = array();
    $s->month = array();
    $s->maker = array();
    $s->name = array();
    $ship_a = array();
    
    $start = Carbon::createFromFormat('Y-m-d', $date[0])->hour(0)->minute(0)->second(0);
    $end = Carbon::createFromFormat('Y-m-d', $date[1])->hour(23)->minute(59)->second(59);
    
    $s->message = array();
    $attrs = array_flip(array_merge(array('id','purchase_date', 'auction_name', 'customer_id', 'return_vat_nmh', 'return_recycle_nmh', 'return_car_tax', 'return_liability',  'tic_total', 'vat_percent'), static::$FIELDS));
    foreach ( $cars as $c ) {
      if (!isset($s->service[$c->service_company_id])) {
        $s->service[$c->service_company_id] = static::create_summary($recid++);
      }
      if (!isset($s->customer[$c->customer_id])) {
        $s->customer[$c->customer_id] = static::create_summary($recid++);
      }
      if (!isset($s->auction[$c->auction_name])) {
        $s->auction[$c->auction_name] = static::create_summary($recid++);
      }
      $ym = substr($c->purchase_date, 0,7);
      if (!isset($s->month[$ym])) {
        $s->month[$ym] = static::create_summary($recid++);
      }
      if (!isset($s->maker[$c->car_maker])) {
        $s->maker[$c->car_maker] = static::create_summary($recid++);
      }
      if (!isset($s->name[$c->car_name])) {
        $s->name[$c->car_name] = static::create_summary($recid++);
      }
      $container_date = $c->container_date ? Carbon::createFromFormat('Y-m-d', $c->container_date) : null;
      $ship_time = 'ship.nothing';
      if ($container_date) {
          if ($start > $container_date) {
              $ship_time = 'ship.before';
          }else if ($end < $container_date) {
              $ship_time = 'ship.after';
          } else {
              $ship_time = 'ship.ontime';
          }
      }
      if (!isset($ship_a[$ship_time])) {
        $ship_a[$ship_time] = static::create_summary($recid++);
      }
      

      $service = &$s->service[$c->service_company_id];
      $customer = &$s->customer[$c->customer_id];
      $auction = &$s->auction[$c->auction_name];
      $month = &$s->month[$ym];
      $maker = &$s->maker[$c->car_maker];
      $name = &$s->name[$c->car_name];
      $ship = &$ship_a[$ship_time];

      $all->count++;
      $service->count++;
      $customer->count++;
      $auction->count++;
      $month->count++;
      $maker->count++;
      $name->count++;
      $ship->count++;

      $c->purchase_price_tax= intval($c->purchase_price * $c->vat_percent / 100 );
      $c->bill_price_tax    = intval($c->bill_price * $c->bill_vat / 100 );

      foreach ( static::$FIELDS as $f ) {
        $v = intval($c->$f);
        $all->$f+=$v;
        $service->$f+=$v;
        $customer->$f+=$v;
        $auction->$f+=$v;
        $month->$f+=$v;
        $maker->$f+=$v;
        $name->$f+=$v;
        $ship->$f+=$v;
      }
      $obj = (object)array_intersect_key($c->attributesToArray(),$attrs);
      $obj->recid = $c->id;

      //Recycle
      $obj->recycle_d = $c->recycle;                   // 返戻日
      $obj->recycle_a = $c->recycle_application_date;  // 申請日

        if ($c->tic_send_fee == 480) {
            $obj->gross_margin_nmh = ($c->bill_total_amount-$c->payment_total_amount)/2;  // gross margin nmh
            $obj->return_vat_nmh = ($c->purchase_price_tax)/2;  // return vat nmh
            $obj->return_recycle_nmh = ($c->recycle_amount)/2;  // return recycle nmh
            $obj->return_car_tax = 0;  // return car tax nmh
            $obj->return_liability = 0;  // return liability nmh
            $obj->tic_total = ($c->bill_total_amount-$c->payment_total_amount)/2 + ($c->purchase_price_tax)/2 + ($c->recycle_amount)/2;  // TIC
        } else {
            $obj->gross_margin_nmh = ($c->bill_total_amount-$c->payment_total_amount);  // gross margin nmh
            $obj->return_vat_nmh = $c->purchase_price_tax;  // return vat nmh
            $obj->return_recycle_nmh = $c->returned_recycle;  // return recycle nmh
            $obj->return_car_tax = $c->car_tax_cancel_amount;  // return car tax nmh
            $obj->return_liability = $c->car_liability_insurance_cancel_amount;  // return liability nmh
            $obj->tic_total = 0;  // TIC
        }
      //
      $obj->car_name = $c->car_name;
      $obj->ship = $ship_time;
      $s->car[] = $obj;
    }

    $s->service['all'] = $all;
    $avg = static::create_summary($recid++);
    if ($all->count>0) {
      foreach ( static::$FIELDS as $f ) {
          $avg->$f=intval($all->$f/$all->count);
      }
      $avg->count=1;
    }
    $s->service['avg'] = $avg;
    foreach ( $s->month as $n=>$m ) {
      $avg = static::create_summary($recid++);
      foreach ( static::$FIELDS as $f ) {
          $avg->$f=intval($m->$f/$m->count);
      }
      $avg->count=1;
      $s->month["$n-avg"] = $avg;
    }
    foreach ( ['ship.after','ship.before','ship.nothing','ship.ontime'] as $n ) {
        if (isset($ship_a[$n])) {
            $s->service[$n] = $ship_a[$n];
        }
    }

    ksort($s->month);
    ksort($s->name);

    usort($s->car, function($a, $b) { return $a->purchase_date<$b->purchase_date ? 1 : -1; });
    return $s;
  }
}

